package com.yue.ssa.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yue.ssa.bean.RespBean;
import com.yue.ssa.bean.User;
import com.yue.ssa.common.Constant;
import com.yue.ssa.exception.MyException;
import com.yue.ssa.mapper.UserMapper;
import com.yue.ssa.service.RoleService;
import com.yue.ssa.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RoleService roleService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user;
        HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String sms = req.getParameter("sms");
        if (StringUtils.isNotBlank(sms)) {
            user = getByEmail(username);
            if (user == null) {
                throw new MyException(Constant.EMAIL_NOTEXIST);
            }
        } else {
            user = this.baseMapper.loadUserByUsername(username);
            if (user == null) {
                throw new UsernameNotFoundException("");
            }
        }
        return user;
    }
    @Override
    public RespBean current() {
        return RespBean.ok(SecurityContextHolder.getContext().getAuthentication().getPrincipal());
    }

    @Override
    public RespBean page(String keyword, Integer pageNo, Integer pageSize) {
        IPage<User> page = new Page<>();
        page.setCurrent(pageNo);
        page.setSize(pageSize);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(keyword)) {
            queryWrapper.lambda().like(User::getName, keyword);
            queryWrapper.lambda().or().like(User::getUsername, keyword);
        }
        queryWrapper.lambda().orderByDesc(User::getCreateTime);
//        queryWrapper.select("name");
        queryWrapper.lambda().select(User::getUsername, User::getId, User::getName, User::getTelephone, User::getEmail, User::isEnabled, User::getAvatar);
        return RespBean.ok(this.page(page, queryWrapper));
    }

    @Override
    public RespBean add(User user) {
        if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getName()) || StringUtils.isBlank(user.getTelephone())) {
            throw new MyException(Constant.INCOMPLETE_INFORMATION);
        }
        if (usernameIsExist(user.getUsername())) {
            throw new MyException(Constant.USERNAME_REPEAT);
        }
        user.setCreateTime(new Date());
        user.setEnabled(true);
        user.setPassword(passwordEncoder.encode(Constant.DEFAULT_PASSWORD));
        return RespBean.ok(this.save(user));
    }

    @Override
    public RespBean update(User user) {
        if (StringUtils.isBlank(user.getId()) || StringUtils.isBlank(user.getName()) || StringUtils.isBlank(user.getName()) || StringUtils.isBlank(user.getTelephone())) {
            throw new MyException(Constant.INCOMPLETE_INFORMATION);
        }
        User u = this.getById(user.getId());
        if (u == null) throw new MyException(Constant.BEANID_INVALID);
        if (!user.getUsername().equals(u.getUsername()) && usernameIsExist(user.getUsername())) {
            throw new MyException(Constant.USERNAME_REPEAT);
        }
        return RespBean.ok(this.updateById(user));
    }

    @Override
    public RespBean get(String id) {
        User user = this.getById(id);
        if (user == null) throw new MyException(Constant.BEANID_INVALID);
        user.setRoles(roleService.getRolesByUid(user.getId()));
        return RespBean.ok(user);
    }

    @Override
    public boolean usernameIsExist(String username) {
        Map<String, Object> params = new HashMap<>();
        params.put("username", username);
        return this.listByMap(params).size() > 0;
    }

    @Override
    public RespBean delete(String[] ids) {
        if (ids == null || ids.length == 0) return RespBean.ok(false);
        return RespBean.ok(this.removeByIds(Arrays.asList(ids)));
    }

    @Override
    public RespBean changePassword(String oldPassword, String newPassword) {
        User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new MyException(Constant.ORIGINAL_PASSWORD_ERROR);
        }
        user.setPassword(passwordEncoder.encode(newPassword));
        return update(user);
    }

    @Override
    public RespBean resetPassword(String id) {
        //密码重置为abc123456
        User user = this.getById(id);
        if (user == null) throw new MyException(Constant.BEANID_INVALID);
        user.setPassword(passwordEncoder.encode(Constant.DEFAULT_PASSWORD));
        return update(user);
    }

    @Override
    public User getByEmail(String email) {
//        QueryWrapper<User> queryWrapper=new QueryWrapper();
//        queryWrapper.lambda().eq(User::getEmail,email);
//        User user = this.getOne(queryWrapper);
        User user = this.baseMapper.loadUserByEmail(email);
        return user;
    }
}
